import { sendMessage } from "./socketService";
import { calculatePlayerScoresCore } from "./scoreCalculatorCore";

let scoreWorker = null;
let workerInitFailed = false;
let jobIdCounter = 0;
const pendingJobs = new Map();

const canUseWorker = typeof window !== 'undefined' && typeof window.Worker !== 'undefined';

const dispatchQtMessage = (serverPayload) => {
    if (!serverPayload) {
        return;
    }
    sendMessage({
        type: 'score_calculation',
        gameInfo: serverPayload.gameInfo,
        data: serverPayload.playersForServer,
        messages: serverPayload.sortedMessages
    });
};

const ensureWorker = () => {
    if (!canUseWorker || scoreWorker || workerInitFailed) {
        return scoreWorker;
    }
    try {
        scoreWorker = new Worker(new URL('../workers/scoreCalculator.worker.js', import.meta.url), { type: 'module' });
        scoreWorker.onmessage = (event) => {
            const { id, result, error, serverPayload } = event.data || {};
            const job = pendingJobs.get(id);
            if (!job) {
                return;
            }
            pendingJobs.delete(id);
            if (error) {
                job.reject(new Error(typeof error === 'string' ? error : 'score worker error'));
                return;
            }
            if (job.isSettlementMode && serverPayload) {
                dispatchQtMessage(serverPayload);
            }
            job.resolve(Array.isArray(result) ? result : []);
        };
        scoreWorker.onerror = (event) => {
            workerInitFailed = true;
            if (scoreWorker) {
                scoreWorker.terminate();
                scoreWorker = null;
            }
            const error = new Error(event.message || 'score worker error');
            pendingJobs.forEach(job => job.reject(error));
            pendingJobs.clear();
        };
    } catch (_) {
        workerInitFailed = true;
        scoreWorker = null;
    }
    return scoreWorker;
};

export function calculatePlayerScores(players, messages, winTeam, pointPool, gameName = '游戏', isSettlementMode = false) {
    const { playersWithScores, serverPayload } = calculatePlayerScoresCore({
        players,
        messages,
        winTeam,
        pointPool,
        gameName,
        isSettlementMode
    });
    if (isSettlementMode && serverPayload) {
        dispatchQtMessage(serverPayload);
    }
    return playersWithScores;
}

export function calculatePlayerScoresAsync(players, messages, winTeam, pointPool, gameName = '游戏', isSettlementMode = false) {
    const worker = ensureWorker();
    if (!worker) {
        return Promise.resolve(
            calculatePlayerScores(players, messages, winTeam, pointPool, gameName, isSettlementMode)
        );
    }

    return new Promise((resolve, reject) => {
        const jobId = ++jobIdCounter;
        pendingJobs.set(jobId, { resolve, reject, isSettlementMode });
        try {
            worker.postMessage({
                id: jobId,
                payload: {
                    players,
                    messages,
                    winTeam,
                    pointPool,
                    gameName,
                    isSettlementMode
                }
            });
        } catch (error) {
            pendingJobs.delete(jobId);
            if (scoreWorker) {
                scoreWorker.terminate();
                scoreWorker = null;
            }
            workerInitFailed = true;
            reject(error);
        }
    });
}
